/****************************************************************************
 * Copyright (C) 2009-2010 SciTouch LLC
 * 
 * This file is part of Indigo toolkit.
 * 
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 3 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 * 
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 ***************************************************************************/

#ifndef __molecule_scaffold_detection_h_
#define __molecule_scaffold_detection_h_
#include "graph/scaffold_detection.h"
#include "graph/max_common_subgraph.h"
#include "molecule/molecule.h"

//class for searching scaffold molecule from molecules set
class MoleculeScaffoldDetection: public ScaffoldDetection {
   public:

   //class for keeping molecules
   class MoleculeBasket:public ScaffoldDetection::GraphBasket {
   public:
      MoleculeBasket();
      virtual ~MoleculeBasket();

      //initializes molecules basket
      void initBasket(const ObjArray<Molecule>* mol_set, ObjArray<Molecule>* basket_set, int max_number);
      //this method adds molecules from set (defines with edges and vertices lists) to basket queue 
      virtual void addToNextEmptySpot(const Graph& graph, Array<int> &v_list, Array<int> &e_list);

      virtual const Graph& getGraphFromSet(int idx) const {return (const Graph&)_searchStructures->at(_orderArray[idx]); }

      virtual int getMaxGraphIndex();


      //returns ptr of molecule in basket with index
      virtual const Graph& getGraph(int index) const;
      //adds new molecule to queue and returns ptr of that
      Molecule& pickOutNextMolecule();


      int (*cbSortSolutions) (const Molecule &mol1, const Molecule &mol2, const void *userdata);



      DEF_ERROR("Mol basket");
      

   private:
      virtual void _sortGraphsInSet();

      
      
      static int _compareEdgeCount(const int &i1,const int &i2,const void* context);
      static int _compareRingsCount(const Molecule& m1, const Molecule& m2, const void* context);

      const ObjArray<Molecule>* _searchStructures;
      ObjArray<Molecule>* _basketStructures;

      MoleculeBasket(const MoleculeBasket&); //no implicit copy
   };

private:
   void _searchScaffold(Molecule& scaffold, bool approximate);

public:
   MoleculeScaffoldDetection (const ObjArray<Molecule>* mol_set);
   
   //two main methods for extracting scaffolds
   //extracting exact scaffold from molecules set
   void extractExactScaffold (Molecule& scaffold) {_searchScaffold(scaffold, false); }
   //extracting approximate scaffold from molecule set
   void extractApproximateScaffold(Molecule& scaffold) {_searchScaffold(scaffold, true); }


   int (*cbSortSolutions) (const Molecule &mol1, const Molecule &mol2, const void *userdata);

   int flags;

   const ObjArray<Molecule>* searchStructures;
   ObjArray<Molecule>* basketStructures;

   DEF_ERROR("Molecule Scaffold detection");
};

#endif
